#pragma once
#include <memory>
#include <linux/videodev2.h>
#include <mutex>
#include <thread>
#include <functional>
#include <condition_variable>
#include <vector>


#ifdef TARGET_RK356X
#ifdef __cplusplus
#include "rga/im2d.hpp"
#else
#include "rga/im2d.h"
#endif
#include <rga/RgaUtils.h>
// #include "rga/utils.h"
#include <arm_neon.h>
#include "rga.h"
#endif

struct video
{
	int width;//摄像头采集图像宽
	int height;//摄像头采集图像高
	char *mmapbuf[4];//保存映射的地址
	int mmap_size;/*映射缓冲区大小*/
};

int Video_Init(char *dev,struct video *video_info);

void yuv_to_rgb(unsigned char *yuv_buffer,unsigned char *rgb_buffer,int iWidth,int iHeight);







class camera
{

public:
	typedef struct 
	{
		int width = 0;//摄像头采集图像宽
		int height = 0 ;//摄像头采集图像高
		char *mmapbuf[4] = {NULL};//保存映射的地址
		int mmap_size = 0;/*映射缓冲区大小*/
	}camera_info;

	typedef enum
	{
		PIXEL_YUYV,
		PIXEL_NV12,
		PIXEL_NV21,
		PIXEL_RGB,
	}Cam_pixelformat;

	struct PixelFormatPriority {
		__u32 v4l2_format;
		const char* description;
		#ifdef TARGET_RK356X
		enum _Rga_SURF_FORMAT rk_rga_format;
		// uint32_t rk_rga_format;
		#endif
	};
	static const camera::PixelFormatPriority priority_formats[];
public:
	camera(const char *dev);
	~camera();
	camera_info * camera_init(uint32_t width,uint32_t height,camera::Cam_pixelformat pf,
											std::function<void(std::vector<char>, int ,int ,void *)> cam_recv,
											std::function<void(int)> recvError,
											void *p	);
	void camera_deInit();
	void yuv_to_rgb(char *yuv_buffer,
				char *rgb_buffer,int iWidth,int iHeight); 
	void  yuyv_to_nv12(char *yuyv_in, char * nv12,
					int width,int height);
	void nv12_to_rgb(unsigned char *nv12_buffer, unsigned char *rgb_buffer, 
					int width, int height) ;
	void nv21_to_nv12(unsigned char *nv21_buffer, unsigned char *nv12_buffer, 
					int width, int height) ;
	void nv21_to_rgb(unsigned char *nv21, unsigned char * nv12,int width,int height);

	void nv24_to_nv12(uint8_t* nv24, uint8_t* nv12, int width, int height);
	void nv24_to_rgb888(uint8_t* nv24, uint8_t* rgb, int width, int height) ;	
	void nv24_to_nv21(uint8_t* nv24, uint8_t* nv21, int width, int height);
	void nv24_to_nv16(uint8_t* nv24, uint8_t* nv16, int width, int height);
	void nv24_to_nv16_neon(uint8_t* nv24, uint8_t* nv16, int width, int height) ;
	void rk_rga_init(int src_Width,int src_Height,int src_format,int dst_Width,int dst_Height,int dst_format);
	int  convert(char *src_buffer,char *dts_buffer);	
	void rk_rga_deinit();
	void set_quit() ;
private:

	std::shared_ptr<camera::camera_info> cam_inf ;
	const char *path;
	int camera_fd = -1;
	int type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
	struct v4l2_format video_format;
    struct v4l2_requestbuffers video_requestbuffers;

	std::mutex mtx;
	std::condition_variable cv;

	bool thread_run = false;

	std::function<void(std::vector<char> , int ,int ,void *)> recv;

	uint32_t max_buf_count = 10;
	void enumerate_formats_and_resolutions(int camera_fd,int type);
	
	camera::Cam_pixelformat format__;

	uint32_t Cam_pielformat_in = 0;



#ifdef TARGET_RK356X
	im_rect src_rect;
	im_rect dst_rect;
	rga_buffer_t src;
	rga_buffer_t dst;
	// rga_buffer_handle_t src_handle = 0;
	// rga_buffer_handle_t dst_handle = 0;
	size_t nv24_size = 0;

#endif	
	int src_width = 0, src_height = 0, src_format=0 ;
    int dst_width = 0, dst_height = 0, dst_format=0 ;
    int src_buf_size, dst_buf_size;

    char* src_buf = NULL;
    char* dst_buf = NULL;


};
